#ifndef GY_INSERTWIDGETCONTROL_H
#define GY_INSERTWIDGETCONTROL_H

#include <QObject>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QVariant>
#include <QMouseEvent>
#include <QModelIndex>

#include "GY_ControlLibrary_global.h"

/**
 * @brief The InesertWidgetIndex struct 界面索引结构体
 */
struct InesertWidgetIndex
{
    int row;
    int col;
    InesertWidgetIndex(){
        row = -1;
        col = -1;
    }
    InesertWidgetIndex& operator = (const InesertWidgetIndex& val)
    {
        row = val.row;
        col = val.col;
        return *this;
    }
};
Q_DECLARE_METATYPE(InesertWidgetIndex)


/**
 * @brief The PaddingTransparentWidget 尾行小于当前列填充的空白界面
 * 保持布局对齐
 */
class GY_CONTROLLIBRARY_EXPORT PaddingTransparentWidget :public QWidget
{
    Q_OBJECT
public:
    explicit PaddingTransparentWidget(QWidget *parent = nullptr)
        :QWidget(parent){
        this->setStyleSheet("QTableView{background:transparent;}"); //使背景透明化
    }
};


/**
 * @brief The GY_InsertWidgetControl class 布局控件
 * 可在该布局器界面中插 QWidget界面
 */
namespace Ui {
class GY_InsertWidgetControl;
}
class GY_CONTROLLIBRARY_EXPORT GY_InsertWidgetControl : public QWidget
{
    Q_OBJECT

signals:
    /**
     * @brief sigWidgetClicked 点击界面 返回该界面 行列索引和对象
     * @param 首行首列为 (1,1)
     */
    void sigWidgetClicked(const InesertWidgetIndex,const QWidget *);

    /**
     * @brief sigWidgetClicked 双击击界面 返回该界面
     * 首行首列为(1，1)
     * @param int 所在布局下标(第几个widget)
     */
    void sigWidgetDoubleClicked(const InesertWidgetIndex,const QWidget *);

public:
    explicit GY_InsertWidgetControl(QWidget *parent = nullptr);
    ~GY_InsertWidgetControl();
public:

    /**
     * @brief addWidget 末尾添加界面
     * @param rowID     界面id
     * @param widget    界面
     */
    template<typename T>
    void addWidget(T *widget)
    {
        QHBoxLayout *currRwoLayout = dynamic_cast<QHBoxLayout*>(m_layout->itemAt(m_layout->count() - 1));

        if(m_layout)
        {
            for(int i = m_layout->count() - 1; i >= 0; i--)
            {
                PaddingTransparentWidget *transparentWidget = dynamic_cast<PaddingTransparentWidget *>(m_layout->itemAt(i)->widget());
                if(transparentWidget)
                    delete m_layout->takeAt(i);
            }
        }

        if(currRwoLayout && getCurrRowInsertNullControl(currRwoLayout))
        {
            clearEmptyControl(currRwoLayout);
        }

        if(!currRwoLayout || currRwoLayout->count() % m_colCount == 0)
        {
            currRwoLayout = createRowLayout();
            m_layout->addLayout(currRwoLayout);
        }else
        {
            //移除当前行部件中的空白部件
            clearEmptyControl(currRwoLayout);
        }
        //必须设置界面大小
        widget->setFixedSize(m_insertWidgetWidth, m_insertWidgetHeight);
        currRwoLayout->addWidget(widget);
        //如果当前行不满足列数、填充空白部件保证布局对齐
        int currentWidgets = getCurrRowInsertNullControl(currRwoLayout);
        if(currentWidgets < m_colCount)
        {
            //计算需要添加的空白数量
            int emptyControl = m_colCount - currentWidgets;
            for(int i = 0; i < emptyControl; i++)
            {
                PaddingTransparentWidget *transparentWidget = new PaddingTransparentWidget();
                transparentWidget->setFixedSize(m_insertWidgetWidth, m_insertWidgetHeight);
                currRwoLayout->addWidget(transparentWidget);
            }
        }

        if(!m_allSaveWidgetList.contains(widget))
            m_allSaveWidgetList.append(widget);
    }

    /**
     * @brief setColCount 可设置布局中列数
     * @param colCount
     */
    void setColCount(const int &colCount){m_colCount = colCount;};


    /**
     * @brief setWidgetSize 设置所有界面大小
     * @param height 高度
     * @param widgth 宽度
     */
    void setWidgetSize(const int &height, const int &widgth);


    /**
     * @brief removeWidget 删除界面
     * @param widget
     */
    bool removeWidget(QWidget* widget);

    /**
     * @brief clear 清除所有布局和界面
     */
    void clear();

    /**
     * @brief getCurrSelectWidget 获取当前选中widget
     * @return
     */
    QWidget* getCurrSelectWidget();

    /**
     * @brief getWidget 通过行列下标获取widget
     * @param row 界面所在行
     * @param col   界面所在列
     * @return
     */
    QWidget* getWidget(const int &findRow, const int &findCol);

    /**
     * @brief getWidgetIndex 返回目标界面的索引
     * @param targetWidget
     * @return
     */
    InesertWidgetIndex getWidgetIndex(const QWidget* targetWidget = nullptr);



    /**
     * @brief setLayoutSpacing 设置每行之间的间距
     * @param width
     */
    void setRowSpacing(const int &spacing);

    /**
     * @brief setColSpacing 设置每列之间的间距
     * @param spacing
     */
    void setColSpacing(const int &spacing);

    /**
     * @brief inertWidget 指定位置插入界面
     * @param row   行下标
     * @param col   列下标
     * @param insertWidget  目标界面
     * @brief 首行首列为 (1,1) 插入首行首列时传入(1,1)
     */
    bool inertWidget(const int &row,const int &col,QWidget *insertWidget);

    /**
     * @brief removeOneWidget 删除指定位置界面
     * @param row   行下标
     * @param col   列下标
     * @param insertWidget  目标界面
     * @brief 首行首列为 (1,1) 删除首行首列时传入(1,1)
     */
    bool removeOneWidget(const int &row,const int &col);

    /**
     * @brief getAllWidget 获取所有widget
     * @return
     */
    QList<QWidget*> getAllWidget();

    /**
     * 加载筛选后的界面
     */
    template<typename T>
    void loadResetWidget(QList<T*> widgetList)
    {
        //删除布局内所有界面 重新添加
        if(m_layout)
        {
            for(int i = m_layout->count() - 1; i >= 0; i--)
            {
                QHBoxLayout *currRwoLayout = dynamic_cast<QHBoxLayout*>(m_layout->itemAt(i));
                if(currRwoLayout)
                {
                    QLayoutItem *item;
                    while((item = currRwoLayout->takeAt(0)) != nullptr)
                    {
                        if(item->widget())
                        {
                            item->widget()->setParent(nullptr);
                        }
                        delete  item;
                    }
                }

            }
        }
        for(int i = 0; i < widgetList.size(); i++)
        {
            addWidget(widgetList.at(i));
        }
    }

    /**
     * @brief loadReset 筛选后重置所有界面
     */
    void resetWidget();

protected:

    /**
     * @brief createRowLayout 创建一行布局
     * @return
     */
    QHBoxLayout *createRowLayout();

    /**
     * @brief resize 界面大小发生变化 重新自适应布局
     */
    void resizeEvent(QResizeEvent *event) override;

    /**
     * @brief mousePressEvent 鼠标单机事件
     * @param event
     */
    void mousePressEvent(QMouseEvent *event) override;
    /**
     * @brief mousePressEvent 鼠标双击事件
     * @param event
     */
    void mouseDoubleClickEvent(QMouseEvent *event) override;
private:

    /**
     * @brief updateCurrLayout 界面大小发生变化、对列数布局进行调整更新
     */
    void updateCurrLayout();

    /**
     * @brief getCurrRowInsertNullControl 获取最后一行填充的非自定义控件
     * @return 填充控件数量
     */
    int getCurrRowInsertNullControl(QHBoxLayout *layout);

    /**
     * @brief clearEmptyControl 清除行中的填充控件
     * @param layout
     */
    void clearEmptyControl(QHBoxLayout *layout);

    /**
     * @brief insertOrRemoveOn 插入或删除界面
     * @param row
     * @param col
     * @param targetWidget   目标界面
     * @param flag   flag = 0 时添加 flag=1时删除
     */
    bool insertOrRemoveOn(const int &row,const int &col,const int &flag, QWidget *targetWidget = nullptr);

    /**
     * @brief setupLayout初始化布局
     */
    void setupLayout();

private:

    Ui::GY_InsertWidgetControl *ui;

    QWidget *m_currSelectWidget = nullptr; //当前选中Widget
    QVBoxLayout *m_layout;

    QList<QWidget*> m_allSaveWidgetList;//保存的所有界面

    //默认添加的widget宽高
    int m_insertWidgetHeight = 250;
    int m_insertWidgetWidth = 300;

    //默认四列 具体列数根据界面代大小而变
    int m_colCount = 4;

    //默认每行的列宽
    int m_colSpacing = 20;
};

#endif // GY_INSERTWIDGETCONTROL_H
